import axios, { AxiosError, AxiosRequestConfig } from 'axios'
// import { message } from 'antd'
// 在js文件中使用redux的数据（不是组件，所以不能使用useSelector()这个钩子去获取）
import store from '@/store'
import { login, logout } from '@/store/actions/login'
import { delProfile } from '@/store/actions/profile'
// 第三方模块histrory 参考地址：https://www.cnblogs.com/yuanjili666/p/13740385.html
import { createHashHistory } from 'history'
import { error } from './tools'
import type { Token } from '@/types/login'
const history = createHashHistory()
export const baseURL = 'http://geek.itheima.net/v1_0/'
// 创建 axios实例
const instance = axios.create({
  baseURL,
  timeout: 5000,
})
// 添加请求拦截器
instance.interceptors.request.use(
  (config) => {
    // 获取token
    const { token }: Token = store.getState().login!
    // 如果有token，就往请求头中携带token
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    }
    return config
  },
  (error) => {
    // 对请求错误做些什么
    return Promise.reject(error)
  }
)

// 添加响应拦截器
instance.interceptors.response.use(
  (res) => res.data,
  async (err: AxiosError<{ message: string }>) => {
    // 对响应错误做点什么
    // 如果请求接口网络超时，也需要做处理，err 中没有response
    if (!err.response) {
      // 暂时这样处理，这样 每个请求都会提示
      error('网络繁忙，请稍后重试')
      return Promise.reject('网络繁忙，请稍后重试')
    }
    // 401错误（未授权:token过期或者token无效或者没有携带token）
    if (err.response.status && err.response.status === 401) {
      // 获取token
      const { token, refresh_token }: Token = store.getState().login!
      if (!token) {
        // 没有token,那就登录
        error('请重新登录', () => {
          // 清除token
          store.dispatch(logout())
          // 清除user
          store.dispatch(delProfile())
          // 跳转到登录页
          history.push('/login')
        })
        return
      }
      // 有token，但是token无效
      if (!refresh_token) {
        // refresh_token也过期了
        error('请重新登录', () => {
          // 清除token
          store.dispatch(logout())
          // 清除user
          store.dispatch(delProfile())
          // 跳转到登录页
          history.push('/login')
        })
        return
      }
      // 有token，但是token无效，但是有refresh_token,那么需要拿着refresh_token去刷新得到最新的token
      try {
        // 此时只能使用axios的原生对象去发起请求
        const res = await axios({
          url: `${baseURL}authorizations`,
          method: 'put',
          headers: {
            Authorization: 'Bearer ' + refresh_token,
          },
        })
        const token = res.data.data.token
        // 更新redux数据
        store.dispatch(login({ token, refresh_token }))
        // 重新完成上次未完成的请求:err.config中保存我们发送axios请求所有参数
        return instance(err.config as AxiosRequestConfig)
      } catch (err) {
        // 可能拿不到
        error('请重新登录', () => {
          // 清除token
          store.dispatch(logout())
          // 清除user
          store.dispatch(delProfile())
          // 跳转到登录页
          history.push('/login')
        })
      }
    }
    // 非401的错误状态码及网络异常外的错误都会走这里
    error(err.response.data.message)
    return Promise.reject(err)
  }
)

// 对axios返回的数据做类型限制
type Data<T> = {
  code: number
  message: string
  data: T
}
// 导出请求函数
export function http<T>(url: string, method = 'get', submitData?: Object) {
  return instance<T, Data<T>>({
    method,
    url,
    [method.toUpperCase() === 'GET' ? 'params' : 'data']: submitData,
  })
}
